use axum::{
    extract::{Extension, Path},
    Json,
};
use serde::{Deserialize, Serialize};
use sqlx::{MySql, Pool};

use crate::{jwt::Claims, res::Res, utils::check_admin};

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct CreateMenu {
    name: String,
    pic: String,
    price: i32,
    description: String,
    rank: Option<i32>,
}

pub async fn create_menu(
    claims: Claims,
    menu: Json<CreateMenu>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    // 管理员才可以添加菜单
    let is_admin = check_admin(user_id, &pool).await;

    if !is_admin {
        res.set_code(-10);
        res.set_msg("只有管理员可以添加菜");
        return res;
    }

    // 添加厨师数据到数据库
    let id = match sqlx::query!(
        r#"insert into 
        menus(
           name,pic, price, description, rank
        ) 
        values(?,?,?,?,?)"#,
        &menu.name,
        &menu.pic,
        &menu.price,
        &menu.description,
        &menu.rank
    )
    .execute(&pool)
    .await
    {
        Ok(v) => {
            // 插入后的用户编号
            v.last_insert_id()
        }
        Err(e) => {
            if e.to_string().contains("Duplicate entry") {
                res.set_code(-1);
                res.set_msg("已经添加过厨师信息");
                return res;
            }

            log::error!("添加厨师数据出错:{}", e);
            res.set_code(-2);
            res.set_msg("服务端出错，请联系管理");
            return res;
        }
    };

    res.set_data(id);
    res
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct ListMenu {
    id: i32,
    name: String,
    pic: String,
    price: i32,
    rank: Option<i32>,
    created_at: Option<String>,
}

/// 菜单列表
pub async fn get_menus(Extension(pool): Extension<Pool<MySql>>) -> Res<Vec<ListMenu>> {
    let mut res = Res::default();
    let rs = match sqlx::query!("SELECT * FROM menus order by rank desc")
        .fetch_all(&pool)
        .await
    {
        Ok(v) => v,
        Err(e) => {
            log::error!("获取菜单列表出错:{}", e);
            res.set_code(-1);
            res.set_msg("获取菜单列表出错");
            return res;
        }
    };

    let mut menus = vec![];
    for v in rs {
        menus.push(ListMenu {
            id: v.id,
            name: v.name,
            pic: v.pic,
            price: v.price,
            rank: v.rank,
            created_at: match v.created_at {
                Some(v) => Some(v.to_string()),
                None => None,
            },
        });
    }

    res.set_data(menus);

    res
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct MenuDetail {
    id: i32,
    name: String,
    pic: String,
    price: i32,
    description: String,
}

/// 菜单详情
pub async fn get_menu_detail(
    Path(id): Path<i32>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<MenuDetail> {
    let mut res = Res::default();
    let rs = match sqlx::query!("SELECT * FROM menus where id=?", id)
        .fetch_one(&pool)
        .await
    {
        Ok(v) => v,
        Err(e) => {
            log::error!("获取菜单详情出错:{}", e);
            res.set_code(-1);
            res.set_msg("获取菜单详情出错");
            return res;
        }
    };

    res.set_data(MenuDetail {
        id: rs.id,
        name: rs.name,
        pic: rs.pic,
        price: rs.price,
        description: rs.description,
    });

    res
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct EditMenu {
    name: String,
    pic: String,
    price: i32,
    description: String,
    rank: Option<i32>,
}

/// 编辑套餐
pub async fn edit_menu(
    claims: Claims,
    Path(id): Path<i32>,
    menu: Json<EditMenu>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    // 管理员才可以编辑菜单
    let is_admin = check_admin(user_id, &pool).await;

    if !is_admin {
        res.set_code(-10);
        res.set_msg("只有管理员可以添加菜");
        return res;
    }

    let rows_affected = match sqlx::query!(
        r#"update menus 
           set name=?, pic=?, price=?, description=?, rank=?
           where id=?
        "#,
        &menu.name,
        &menu.pic,
        &menu.price,
        &menu.description,
        &menu.rank,
        id,
    )
    .execute(&pool)
    .await
    {
        Ok(v) => {
            // 受影响的行数
            v.rows_affected()
        }
        Err(e) => {
            log::error!("编辑菜单出错:{}", e);
            res.set_code(-2);
            res.set_msg("服务端出错，请联系管理");
            return res;
        }
    };

    res.set_data(rows_affected);

    res
}

/// 删除套餐
pub async fn delete_menu(
    claims: Claims,
    Path(id): Path<i32>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    // 管理员才可以删除菜单
    let is_admin = check_admin(user_id, &pool).await;

    if !is_admin {
        res.set_code(-10);
        res.set_msg("只有管理员可以产出菜单");
        return res;
    }

    let rows_affected = match sqlx::query!("delete from menus where id=?", id)
        .execute(&pool)
        .await
    {
        Ok(v) => {
            // 插入后的用户编号
            v.rows_affected()
        }
        Err(e) => {
            log::error!("删除菜单出错:{}", e);
            res.set_code(-2);
            res.set_msg("服务端出错，请联系管理");
            return res;
        }
    };

    res.set_data(rows_affected);

    res
}
